{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.继承\n",
    "\n",
    "代码裤子：<https://github.com/lotapp/BaseCode>\n",
    "\n",
    "在线编程：<https://mybinder.org/v2/gh/lotapp/BaseCode/master>\n",
    "\n",
    "在线预览：<http://github.lesschina.com/python/base/oop/2.继承与多态.html>\n",
    "\n",
    "### 2.1.单继承\n",
    "在OOP中，当我们定义一个Class的时候，可以从某个现有的Class继承\n",
    "\n",
    "新的Class称为子类，而被继承的class称为 基类 或者 父类\n",
    "\n",
    "Python的继承格式 ==> **xxx(base_class)**\n",
    "\n",
    "小明兴高采烈的听着老师开新课，不一会就看见了一个演示Demo："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "动物会吃\n",
      "动物会吃\n"
     ]
    }
   ],
   "source": [
    "class Animal(object):\n",
    "    def eat(self):\n",
    "        print(\"动物会吃\")\n",
    "\n",
    "class Cat(Animal):\n",
    "    # 注意一下Python的继承格式\n",
    "    pass\n",
    "\n",
    "class Dog(Animal):\n",
    "    pass\n",
    "\n",
    "def main():\n",
    "    cat = Cat()\n",
    "    dog = Dog()\n",
    "    cat.eat()\n",
    "    dog.eat()\n",
    "\n",
    "if __name__ == \"__main__\":\n",
    "    main()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "当听到老师说：“**私有**的属性方法 **不会被子类继承** ”的时候，小明心里一颤，联想到之前讲的 **类属性**、**实例属性**、**实例方法**、**类方法**、**静态方法**，于是赶紧写个Demo验证一下："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "我是实例方法，动物会吃哦～\n",
      "动物\n",
      "我是类方法，动物会叫哦\n",
      "我是类方法，动物会叫哦\n",
      "我是类方法，动物会叫哦\n",
      "我是静态方法，动物会玩耍哦\n",
      "我是静态方法，动物会玩耍哦\n",
      "我是静态方法，动物会玩耍哦\n"
     ]
    }
   ],
   "source": [
    "class Animal(object):\n",
    "    # 类属性\n",
    "    name = '动物'\n",
    "\n",
    "    def __init__(self):\n",
    "        # 实例属性\n",
    "        self.age = 1\n",
    "\n",
    "    def __bug(self):\n",
    "        \"\"\"实例私有方法\"\"\"\n",
    "        print(\"我是动物类身上的私有方法：bug\")\n",
    "\n",
    "    def eat(self):\n",
    "        \"\"\"实例方法\"\"\"\n",
    "        print(\"我是实例方法，动物会吃哦～\")\n",
    "\n",
    "    @classmethod\n",
    "    def call(cls):\n",
    "        \"\"\"类方法\"\"\"\n",
    "        print(\"我是类方法，动物会叫哦\")\n",
    "\n",
    "    @staticmethod\n",
    "    def play():\n",
    "        \"\"\"静态方法\"\"\"\n",
    "        print(\"我是静态方法，动物会玩耍哦\")\n",
    "\n",
    "\n",
    "class Dog(Animal):\n",
    "    pass\n",
    "\n",
    "\n",
    "def main():\n",
    "    dog = Dog()\n",
    "    # 实例属性\n",
    "    print(dog.age)\n",
    "    # 实例方法\n",
    "    dog.eat()\n",
    "\n",
    "    # 类属性\n",
    "    print(dog.name)\n",
    "    # 类方法\n",
    "    dog.call()\n",
    "    Dog.call()\n",
    "    Animal.call()\n",
    "\n",
    "    # 静态方法\n",
    "    dog.play()\n",
    "    Dog.play()\n",
    "    Animal.play()\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    main()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "来张图就懂了，不是 **私有的** 都能访问：\n",
    "\n",
    "![一张图就懂了](https://images2018.cnblogs.com/blog/1127869/201806/1127869-20180621124912490-1604470767.png)\n",
    "\n",
    "这时候，小明老高兴了，单回头一想 ==> 不科学啊，dog应该有其对应的方法吧，C#有**虚方法**重写，Python怎么搞？在**子类**里面又**怎么调用父类方法**呢？\n",
    "\n",
    "对于小明的提示老师很高兴，于是点名小潘来写一个子类调用父类的demo（老师昨天从窗户里看见小潘有预习）："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "文雅的吃饭\n",
      "文雅的吃饭\n"
     ]
    }
   ],
   "source": [
    "# 调用父类的方法\n",
    "class Father(object):\n",
    "    def eat(self):\n",
    "        print(\"文雅的吃饭\")\n",
    "\n",
    "\n",
    "class Son(Father):\n",
    "    def eat(self):\n",
    "        # 调用父类方法第1种（super().方法）\n",
    "        super().eat()\n",
    "\n",
    "\n",
    "class GrandSon(Son):\n",
    "    def eat(self):\n",
    "        # 调用父类方法第2种（记得传self）\n",
    "        Son.eat(self)\n",
    "\n",
    "\n",
    "def main():\n",
    "    xiaoming = Son()\n",
    "    xiaoming.eat()\n",
    "\n",
    "    xiaoli = GrandSon()\n",
    "    xiaoli.eat()\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    main()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "一般我们使用`super().方法`来调用父类方法\n",
    "\n",
    "第二种方法`类名.方法(self)`千万别忘记传self哦\n",
    "\n",
    "对了，C#是用base关键词，别搞混了\n",
    "\n",
    "小明这时候可不高兴了，风头怎么能被小潘全部抢走呢，赶紧问问旁边同样预习的伟哥\n",
    "\n",
    "不一会儿淡定的发了份重写父类方法的demo给老师："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "小明喜欢文雅的吃饭\n",
      "小潘喜欢大口吃饭大口喝酒\n"
     ]
    }
   ],
   "source": [
    "# 重写父类方法==>子类和父类有同名方法\n",
    "class Father(object):\n",
    "    def __init__(self, name):\n",
    "        self.name = name\n",
    "\n",
    "    def eat(self):\n",
    "        print(\"%s喜欢文雅的吃饭\" % self.name)\n",
    "\n",
    "\n",
    "class Son(Father):\n",
    "    def __init__(self, name):\n",
    "        super().__init__(name)\n",
    "\n",
    "    def eat(self):\n",
    "        print(\"%s喜欢大口吃饭大口喝酒\" % self.name)\n",
    "\n",
    "\n",
    "def main():\n",
    "    xiaoming = Father(\"小明\")\n",
    "    xiaoming.eat()\n",
    "\n",
    "    xiaopan = Son(\"小潘\")\n",
    "    xiaopan.eat()\n",
    "\n",
    "\n",
    "if __name__ == \"__main__\":\n",
    "    main()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "老师半喜半忧的说道：“小明同学啊，你也老大不小了，怎么跟孩子一样啊？案例不错，但是怎么能人身攻击人家小潘了？”\n",
    "\n",
    "当子类和父类都存在相同的`eat()`方法时，我们说，子类的`eat()`覆盖了父类的`eat()`\n",
    "\n",
    "在代码运行的时候，总是会调用子类的`eat()` 这样，我们就获得了继承的另一个好处：**多态**\n",
    "\n",
    "### 2.2.多继承\n",
    "\n",
    "在讲`多态`之前，我们先引入一下Python的 **多继承** 对，你没有听错\n",
    "\n",
    "Java、C#都是单继承，多实现。Python和C++一样，可以多继承，先不要吐槽，**规范使用**其实很方便的\n",
    "\n",
    "来个案例看看："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "文雅的吃饭\n",
      "小碎步\n"
     ]
    }
   ],
   "source": [
    "# 多继承引入\n",
    "class Father(object):\n",
    "    def eat(self):\n",
    "        print(\"文雅的吃饭\")\n",
    "\n",
    "\n",
    "class Mom(object):\n",
    "    def run(self):\n",
    "        print(\"小碎步\")\n",
    "\n",
    "\n",
    "class Son(Father, Mom):\n",
    "    pass\n",
    "\n",
    "\n",
    "def main():\n",
    "    son = Son()\n",
    "    son.eat()\n",
    "    son.run()\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    main()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "继承可以把父类的所有功能都直接拿过来，这样就不必重0开始写代码，子类只需要新增自己特有的方法，也可以把父类不适合的方法覆盖重写\n",
    "\n",
    "注意一个情况，如果父类里面有同名方法咋办了？到底调哪个呢？\n",
    "\n",
    "使用`子类名.__mro__`可以看在调方法的时候搜索顺序\n",
    "\n",
    "一般同名方法都是 **先看自己**有没有，然后看继承顺序，比如这边 **先看Mom再看Father**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "开心的吃饭\n",
      "(<class '__main__.Son'>, <class '__main__.Mom'>, <class '__main__.Father'>, <class 'object'>)\n"
     ]
    }
   ],
   "source": [
    "# 如果父类里面有同名方法怎么知道调哪个？\n",
    "class Father(object):\n",
    "    def eat(self):\n",
    "        print(\"文雅的吃饭\")\n",
    "\n",
    "\n",
    "class Mom(object):\n",
    "    def eat(self):\n",
    "        print(\"开心的吃饭\")\n",
    "\n",
    "\n",
    "class Son(Mom, Father):\n",
    "    pass\n",
    "\n",
    "\n",
    "def main():\n",
    "    son = Son()\n",
    "    son.eat()\n",
    "    print(Son.__mro__)  # 一般同名方法都是先看自己有没有，然后看继承顺序，比如这边先看Mom再看Father\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    main()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Python的多继承最好是当C#或者Java里面的接口使用，这样结构不会混乱(**特殊情况除外**)\n",
    "\n",
    "来个例子：\n",
    "```py\n",
    "class Animal(object):\n",
    "    pass\n",
    "\n",
    "class Flyable(object):\n",
    "    \"\"\"飞的方法\"\"\"\n",
    "    pass\n",
    "\n",
    "class Runable(object):\n",
    "    \"\"\"跑的方法\"\"\"\n",
    "    pass\n",
    "\n",
    "class Dog(Animal, Runable):\n",
    "    pass\n",
    "\n",
    "class Cat(Animal, Runable):\n",
    "    pass\n",
    "\n",
    "class Bird(Animal, Flyable):\n",
    "    pass\n",
    "\n",
    "class Dack(Animal, Runable, Flyable):\n",
    "    \"\"\"鸭子会飞也会跑\"\"\"\n",
    "    pass\n",
    "```\n",
    "和C#一样，Python的 **父类构造函数不会被继承**\n",
    "\n",
    "其实从资源角度也不应该被继承，如果有1w个子类，那每个子类里面都有一个父类方法，想想这是多么浪费的一件事情？\n",
    "\n",
    "---\n",
    "\n",
    "### 2.3.C#继承\n",
    "\n",
    "下课后，小明认真思考总结，然后对照Python写下了C#版的继承：\n",
    "\n",
    "定义一个人类\n",
    "```csharp\n",
    "public class Person\n",
    "{\n",
    "    public string Name { get; set; }\n",
    "    public ushort Age { get; set; }\n",
    "\n",
    "    public Person(string name, ushort age)\n",
    "    {\n",
    "        this.Name = name;\n",
    "        this.Age = age;\n",
    "    }\n",
    "    public void Hi()//People\n",
    "    {\n",
    "        Console.WriteLine(\"Name: \" + this.Name + \" Age: \" + this.Age);\n",
    "    }\n",
    "    public virtual void Show()//People\n",
    "    {\n",
    "        Console.WriteLine(\"Name: \" + this.Name + \" Age: \" + this.Age);\n",
    "    }\n",
    "}\n",
    "```\n",
    "定义一个学生类\n",
    "```csharp\n",
    "public class Student : Person\n",
    "{\n",
    "    #region 属性\n",
    "    /// <summary>\n",
    "    /// 学校\n",
    "    /// </summary>\n",
    "    public string School { get; set; }\n",
    "    /// <summary>\n",
    "    /// 班级\n",
    "    /// </summary>\n",
    "    public string StrClass { get; set; }\n",
    "    /// <summary>\n",
    "    /// 学号\n",
    "    /// </summary>\n",
    "    public string StrNum { get; set; }\n",
    "    #endregion\n",
    "\n",
    "    #region 构造函数\n",
    "    /// <summary>\n",
    "    /// 调用父类构造函数\n",
    "    /// </summary>\n",
    "    /// <param name=\"name\"></param>\n",
    "    /// <param name=\"age\"></param>\n",
    "    public Student(string name, ushort age) : base(name, age)\n",
    "    {\n",
    "\n",
    "    }\n",
    "    public Student(string name, ushort age, string school, string strClass, string strNum) : this(name, age)\n",
    "    {\n",
    "        this.School = school;\n",
    "        this.StrClass = strClass;\n",
    "        this.StrNum = strNum;\n",
    "    } \n",
    "    #endregion\n",
    "\n",
    "    /// <summary>\n",
    "    /// new-隐藏\n",
    "    /// </summary>\n",
    "    public new void Hi()//Student\n",
    "    {\n",
    "        Console.WriteLine(\"Name: \" + this.Name + \" Age: \" + this.Age + \" School: \" + this.School + \" strClass: \" + this.StrClass + \" strNum: \" + this.StrNum);\n",
    "    }\n",
    "    /// <summary>\n",
    "    /// override-覆盖\n",
    "    /// </summary>\n",
    "    public override void Show()//Student\n",
    "    {\n",
    "        Console.WriteLine(\"Name: \" + this.Name + \" Age: \" + this.Age + \" School: \" + this.School + \" strClass: \" + this.StrClass + \" strNum: \" + this.StrNum);\n",
    "    }\n",
    "}\n",
    "```\n",
    "调用一下：\n",
    "```csharp\n",
    "Person p = new Student(\"app\", 10, \"北京大学\", \"001\", \"01001\");\n",
    "p.Hi(); p.Show();\n",
    "\n",
    "Console.WriteLine();\n",
    "\n",
    "Student s = p as Student;\n",
    "s.Hi(); s.Show();\n",
    "```\n",
    "结果:\n",
    "```\n",
    "Name: app Age: 10\n",
    "Name: app Age: 10 School: 北京大学 strClass: 001 strNum: 01001\n",
    "Name: app Age: 10 School: 北京大学 strClass: 001 strNum: 01001\n",
    "Name: app Age: 10 School: 北京大学 strClass: 001 strNum: 01001\n",
    "```\n",
    "---\n",
    "### 2.4C#接口的多实现\n",
    "\n",
    "定义两个接口：\n",
    "```csharp\n",
    "public interface IRun\n",
    "{\n",
    "    //什么都不用加\n",
    "    void Run();\n",
    "}\n",
    "\n",
    "public interface IEat\n",
    "{\n",
    "    void Eat();\n",
    "}\n",
    "```\n",
    "定义一个Dog类来实现两个接口，这样dog就有了run和eat的方法了\n",
    "```csharp\n",
    "var dog = new Dog();\n",
    "dog.Eat();\n",
    "dog.Run();\n",
    "```\n",
    "结果：\n",
    "```\n",
    "狗狗吃\n",
    "狗狗跑\n",
    "```\n",
    "\n",
    "---\n",
    "\n",
    "## 3 多态\n",
    "\n",
    "### 3.1.Python\n",
    "说多态之前说说类型判断，以前我们用`type()` or `isinstance()`\n",
    "\n",
    "**判断一个变量和另一个变量是否是同一个类型**==> `type(a)==type(b)`\n",
    "\n",
    "**判断一个变量是否是某个类型**==> `type(a)==A` or `isinstance(a,A)`\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "True\n",
      "<class '__main__.Dog'>\n",
      "True\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "# 判断一个变量是否是某个类型 ==> isinstance() or type\n",
    "class Animal(object):\n",
    "    pass\n",
    "\n",
    "\n",
    "class Dog(Animal):\n",
    "    pass\n",
    "\n",
    "\n",
    "def main():\n",
    "    dog = Dog()\n",
    "    dog2 = Dog()\n",
    "    print(type(dog) == Dog)\n",
    "    print(type(dog) == type(dog2))\n",
    "    print(type(dog))\n",
    "\n",
    "    print(isinstance(dog, Dog))\n",
    "    print(isinstance(dog, Animal))\n",
    "    # arg 2 must be a type or tuple\n",
    "    # print(isinstance(dog, dog2))\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    main()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "小明老高兴了，终于讲解多态了，不禁问道：“**多态的好处**是啥？”\n",
    "\n",
    "小潘瞥了一眼小明～“废话，肯定为了 **屏蔽子类差异用**的啊，像简单工厂不就干的这个事？\"\n",
    "\n",
    "小明楞了楞，眼巴巴的看着老师继续讲课。\n",
    "\n",
    "设计模式我们会找个专题讲讲，现在给你们说的是Python的基础。\n",
    "\n",
    "Python是动态语言的“**鸭子类型**”，它并不要求严格的继承体系。\n",
    "\n",
    "一个对象只要“看起来像鸭子，走起路来像鸭子”，那它就可以被看做是鸭子（最后会贴一个案例）\n",
    "\n",
    "C#实现多态有很多方式，比如虚方法，比如抽象类，比如接口等等...\n",
    "\n",
    "小明迷迷糊糊的问道：“那 **Python怎么实现多态呢**？”\n",
    "\n",
    "老师看了一眼打断他讲课的小明，然后继续说道～来个简单案例："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "赶时间的吃饭\n",
      "优雅的吃饭\n"
     ]
    }
   ],
   "source": [
    "class People(object):\n",
    "    def eat(self):\n",
    "        print(\"人类会吃饭\")\n",
    "\n",
    "class Father(People):\n",
    "    def eat(self):\n",
    "        print(\"优雅的吃饭\")\n",
    "\n",
    "class Teacher(People):\n",
    "    def eat(self):\n",
    "        print(\"赶时间的吃饭\")\n",
    "\n",
    "# C# 或者 Java里面 写成 eat(People obj)\n",
    "def eat(obj):\n",
    "    obj.eat()\n",
    "\n",
    "def main():\n",
    "    teacher = Teacher()\n",
    "    father = Father()\n",
    "    eat(teacher)\n",
    "    eat(father)\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    main()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "多态的好处在于，如果这时候我再来个Son子类，只要eat()方法编写正确，不用管原来的代码是如何调用的\n",
    "\n",
    "这次小明懂了，为了装一下，说道：”老师老师，我记得C# 或者 Java里面是写成 eat(People obj) 的吧？“\n",
    "\n",
    "老师欣慰的笑了一下，说道：”记得刚才说的`填鸭式`吗？Python这么写有个好处哦，我们来看个案例，然后你自己总结“"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "赶时间的吃饭\n",
      "优雅的吃饭\n",
      "舔着吃\n"
     ]
    }
   ],
   "source": [
    "class People(object):\n",
    "    def eat(self):\n",
    "        print(\"人类会吃饭\")\n",
    "\n",
    "class Father(People):\n",
    "    def eat(self):\n",
    "        print(\"优雅的吃饭\")\n",
    "\n",
    "class Teacher(People):\n",
    "    def eat(self):\n",
    "        print(\"赶时间的吃饭\")\n",
    "\n",
    "class Dog(object):\n",
    "    def eat(self):\n",
    "        print(\"舔着吃\")\n",
    "\n",
    "def eat(obj):\n",
    "    obj.eat()\n",
    "\n",
    "def main():\n",
    "    teacher = Teacher()\n",
    "    father = Father()\n",
    "    eat(teacher)\n",
    "    eat(father)\n",
    "    \n",
    "    # 我们添加一个不是People子类的Dog类，只要有eat方法，参数一样就可以直接调\n",
    "    dog = Dog()\n",
    "    eat(dog)\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    main()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "小明赶紧结合之前学的内容写了个小案例："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "人类会吃饭\n",
      "优雅的吃饭\n",
      "舔着吃饭\n"
     ]
    }
   ],
   "source": [
    "class People(object):\n",
    "    def eat(self):\n",
    "        print(\"人类会吃饭\")\n",
    "\n",
    "class Father(People):\n",
    "    def eat(self):\n",
    "        print(\"优雅的吃饭\")\n",
    "\n",
    "class Dog(object):\n",
    "    def eat(self):\n",
    "        print(\"舔着吃饭\")\n",
    "\n",
    "class Factory(object):\n",
    "    @classmethod\n",
    "    def eat(cls, obj):\n",
    "        if hasattr(obj, \"eat\"):\n",
    "            obj.eat()\n",
    "        else:\n",
    "            raise Exception(\"该类没有eat()方法!\")\n",
    "\n",
    "def main():\n",
    "    people = People()\n",
    "    father = Father()\n",
    "    dog = Dog()\n",
    "    \n",
    "    Factory.eat(people)\n",
    "    Factory.eat(father)\n",
    "    Factory.eat(dog)\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    main()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "小明突然大声说道：”老师老师，我知道了，Python这是吧类的继承和接口继承融合起来了啊，实现多态就相当于C#里面的接口实现多态啊！！！“\n",
    "\n",
    "老师点评道：”你姑且可以这么理解，这些我们后面还会继续说的，这种填鸭式的手段刚开始的确会有点不方便，用着用着你就会觉得挺方便的“\n",
    "\n",
    "---\n",
    "\n",
    "小明认真思考总结，然后对照Python和小潘一起写下了 **C#版的多态**：\n",
    "\n",
    "### 3.2.C#虚方法实现多态\n",
    "\n",
    "定义一个人类：\n",
    "```csharp\n",
    "public class Person\n",
    "{\n",
    "    #region 字段+属性\n",
    "    /// <summary>\n",
    "    /// 姓名\n",
    "    /// </summary>\n",
    "    private string _name;\n",
    "    public string Name\n",
    "    {\n",
    "        get\n",
    "        {\n",
    "            return _name;\n",
    "        }\n",
    "\n",
    "        set\n",
    "        {\n",
    "            _name = value;\n",
    "        }\n",
    "    }\n",
    "    /// <summary>\n",
    "    /// 性别\n",
    "    /// </summary>\n",
    "    private bool _gender;\n",
    "    public bool Gender\n",
    "    {\n",
    "        get\n",
    "        {\n",
    "            return _gender;\n",
    "        }\n",
    "\n",
    "        set\n",
    "        {\n",
    "            _gender = value;\n",
    "        }\n",
    "    }\n",
    "    /// <summary>\n",
    "    /// 年龄\n",
    "    /// </summary>\n",
    "    public short Age { get; set; }\n",
    "    #endregion\n",
    "\n",
    "    #region 构造函数\n",
    "    public Person() { }\n",
    "    public Person(string name, bool gender)\n",
    "    {\n",
    "        this.Name = name;\n",
    "        this.Gender = gender;\n",
    "    }\n",
    "    public Person(string name, bool gender, short age) : this(name, gender)\n",
    "    {\n",
    "        this.Age = age;\n",
    "    }\n",
    "    #endregion\n",
    "\n",
    "    #region 方法\n",
    "    /// <summary>\n",
    "    /// 打招呼\n",
    "    /// </summary>\n",
    "    public virtual void SaiHi()\n",
    "    {\n",
    "        Console.WriteLine(\"我是一个人类！\");\n",
    "    }\n",
    "    #endregion\n",
    "}\n",
    "```\n",
    "定义一个女孩类：\n",
    "```csharp\n",
    "public class Gril : Person\n",
    "{\n",
    "    #region 构造函数\n",
    "    public Gril() { }\n",
    "    public Gril(string name, bool gender) : base(name, gender) { }\n",
    "    public Gril(string name, bool gender, short age) : base(name, gender, age) { }\n",
    "    #endregion\n",
    "\n",
    "    /// <summary>\n",
    "    /// 重写父类方法\n",
    "    /// </summary>\n",
    "    public override void SaiHi()\n",
    "    {\n",
    "        string genderStr = Gender == true ? \"男孩\" : \"女孩\";\n",
    "        Console.WriteLine($\"你好，我叫{Name}，今年{Age}岁了，我是一个腼腆的小{genderStr}\");\n",
    "    }\n",
    "}\n",
    "```\n",
    "定义一个男孩类：\n",
    "```csharp\n",
    "public class Boy : Person\n",
    "{\n",
    "    #region 构造函数\n",
    "    public Boy() { }\n",
    "    public Boy(string name, bool gender) : base(name, gender) { }\n",
    "    public Boy(string name, bool gender, short age) : base(name, gender, age) { }\n",
    "    #endregion\n",
    "\n",
    "    //public void SaiHi()\n",
    "    public override void SaiHi()\n",
    "    {\n",
    "        string genderStr = Gender == true ? \"男孩\" : \"女孩\";\n",
    "        Console.WriteLine($\"你好，我叫{Name}，今年{Age}岁了，我是一个腼腆的小{genderStr}\");\n",
    "    }\n",
    "}\n",
    "```\n",
    "调用：\n",
    "```csharp\n",
    "static void Main(string[] args)\n",
    "{\n",
    "    Person[] persons = { new Person(), new Boy(\"铁锅\", true, 13), new Gril(\"妞妞\", false, 22) };\n",
    "    foreach (var item in persons)\n",
    "    {\n",
    "        //看看item里面到底放的是什么\n",
    "        Console.WriteLine(item.ToString());\n",
    "        item.SaiHi();\n",
    "        Console.WriteLine();\n",
    "    }\n",
    "}\n",
    "```\n",
    "结果：\n",
    "```\n",
    "Polymorphism1.Person\n",
    "我是一个人类！\n",
    "Polymorphism1.Boy\n",
    "你好，我叫铁锅，今年13岁了，我是一个腼腆的小男孩\n",
    "Polymorphism1.Gril\n",
    "你好，我叫妞妞，今年22岁了，我是一个腼腆的小女孩\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "### 3.3.C#抽象类实现多态\n",
    "\n",
    "定义一个动物类：\n",
    "```csharp\n",
    "public abstract class Animal\n",
    "{\n",
    "    /// <summary>\n",
    "    /// 抽象类中可以有正常的方法\n",
    "    /// </summary>\n",
    "    public void Action()\n",
    "    {\n",
    "        Console.WriteLine(\"动物可以动\");\n",
    "    }\n",
    "\n",
    "    /// <summary>\n",
    "    /// 抽象方法必须在抽象类中\n",
    "    /// </summary>\n",
    "    public abstract void Call();\n",
    "}\n",
    "```\n",
    "定义一个猫科动物类（子类必须实现父类抽象方法，如果不实现，那么该类也必须是抽象类）\n",
    "```csharp\n",
    "/// <summary>\n",
    "/// 猫科动物---子类必须实现父类抽象方法，如果不实现，那么该类也必须是抽象类\n",
    "/// </summary>\n",
    "public abstract class Feline : Animal\n",
    "{\n",
    "}\n",
    "```\n",
    "定义一个猫类\n",
    "```csharp\n",
    "public class Cat : Feline\n",
    "{\n",
    "    /// <summary>\n",
    "    /// 子类必须实现父类抽象方法，如果不实现，那么该类也必须是抽象类\n",
    "    /// </summary>\n",
    "    public override void Call()\n",
    "    {\n",
    "        Console.WriteLine(\"喵喵叫~~~\");\n",
    "    }\n",
    "}\n",
    "```\n",
    "定义一个狗类\n",
    "```csharp\n",
    "public class Dog : Animal\n",
    "{\n",
    "    /// <summary>\n",
    "    /// 子类必须实现抽象类中的抽象方法\n",
    "    /// </summary>\n",
    "    public override void Call()\n",
    "    {\n",
    "        Console.WriteLine(\"汪汪叫~~~\");\n",
    "    }\n",
    "}\n",
    "```\n",
    "调用：\n",
    "```csharp\n",
    "Animal[] animals = { new Dog(), new Cat() };\n",
    "foreach (var item in animals)\n",
    "{\n",
    "    item.Call();\n",
    "}\n",
    "```\n",
    "结果：\n",
    "```\n",
    "汪汪叫~~~\n",
    "喵喵叫~~~\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "### 3.4.C#接口实现多态\n",
    "\n",
    "定义一个跑的接口：\n",
    "```csharp\n",
    "public interface IRun\n",
    "{\n",
    "    /// <summary>\n",
    "    /// 接口中可以声明属性，方法，索引器等\n",
    "    /// </summary>\n",
    "    //string Name { get; set; }\n",
    "\n",
    "    void Runing();\n",
    "}\n",
    "```\n",
    "定义一个猫类：\n",
    "```csharp\n",
    "public class Cat : IRun\n",
    "{\n",
    "    public void Runing()\n",
    "    {\n",
    "        Console.WriteLine(\"飞快的跑着上树\");\n",
    "    }\n",
    "}\n",
    "```\n",
    "定义一个学生类：\n",
    "```csharp\n",
    "public class Student : IRun\n",
    "{\n",
    "    public void Runing()\n",
    "    {\n",
    "        Console.WriteLine(\"飞快的跑着去上课\");\n",
    "    }\n",
    "}\n",
    "```\n",
    "调用：\n",
    "```csharp\n",
    "IRun[] objs = { new Student(), new Cat() };\n",
    "foreach (var item in objs)\n",
    "{\n",
    "    item.Runing();\n",
    "}\n",
    "```\n",
    "结果：\n",
    "```\n",
    "飞快的跑着去上课\n",
    "飞快的跑着上树\n",
    "```"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
